package dyl.sys.init;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import dyl.common.util.DylSqlUtil;
import dyl.common.util.JdbcTemplateUtil;
import dyl.common.util.SpringContextUtil;
import dyl.sys.Annotation.Auth;
import dyl.sys.bean.SysAuthRole;
import dyl.sys.bean.SysMenu;
@Service
public class AuthCache {
	public static final Log log = LogFactory.getLog(AuthCache.class);
	@Resource
	private JdbcTemplateUtil jdbcTemplate;
	@PostConstruct
	private void load() throws SQLException{
		log.info("开始角色权限缓存。。");
		cacheRoleAuth(null);
		log.info("开始缓存aciton中方法权限种类。。");
		methodAuthKindCache();
		log.info("开始缓存action对应的MenuId。。");
		acitonMenuIdCatche();
		log.info("权限缓存载入完毕。");
		
		//判断数据库类型
		DatabaseMetaData md = jdbcTemplate.getDataSource().getConnection().getMetaData(); 
		if(md.getDatabaseProductName().equals("MySQL"))DylSqlUtil.isMYSQL=true;
		else if(md.getDatabaseProductName().equals("Oracle"))DylSqlUtil.isORACLE=true;
	}
	/**
	 * 缓存用户角色权限
	 */
	public static Map<BigDecimal,Map<BigDecimal,Set<BigDecimal>>> roleAuthMap = new HashMap<BigDecimal,Map<BigDecimal,Set<BigDecimal>>>();
	public void cacheRoleAuth(BigDecimal roleId){
		List<Object> paraList = new ArrayList<Object>();
		String sql = "";
		if(roleId==null)sql = "select * from sys_auth_role";
		else {
			if(roleAuthMap.get(roleId)!=null)roleAuthMap.get(roleId).clear();//先清空再塞入角色权限
			sql = "select * from sys_auth_role where role_id = ?";
			paraList.add(roleId);
		}
		List<SysAuthRole> sysAuthRoles = jdbcTemplate.queryForListBean(sql,paraList.toArray(),SysAuthRole.class);
		for (SysAuthRole s:sysAuthRoles) {
			if(roleAuthMap.get(s.getRoleId())!=null){//能找到角色下的菜单集合
				if(roleAuthMap.get(s.getRoleId()).get(s.getMenuId())!=null){//能找到该角色下的菜单权限集合
					roleAuthMap.get(s.getRoleId()).get(s.getMenuId()).add(s.getKindId());
				}else{
					Set<BigDecimal> auths = new HashSet<BigDecimal>();
					auths.add(s.getKindId());
					roleAuthMap.get(s.getRoleId()).put(s.getMenuId(),auths);
				}
			}else{
				Map<BigDecimal,Set<BigDecimal>> menuKindMap = new HashMap<BigDecimal, Set<BigDecimal>>();
				Set<BigDecimal> auths = new HashSet<BigDecimal>();
				auths.add(s.getKindId());
				menuKindMap.put(s.getMenuId(),auths);
				roleAuthMap.put(s.getRoleId(),menuKindMap);
			}
		}
	}
	/**
	 * 缓存aciton中方法权限种类，用于拦截其中判断是否有权限进行操作
	 */
	public static Map<String,BigDecimal> methodAuthKindMap = new HashMap<String,BigDecimal>();
	private void methodAuthKindCache(){
		RequestMappingHandlerMapping rmhp =  SpringContextUtil.getApplicationContext().getBean(RequestMappingHandlerMapping.class);
		Map<RequestMappingInfo, HandlerMethod> map = rmhp.getHandlerMethods();  
        for(RequestMappingInfo info : map.keySet()){
        	 Method method = map.get(info).getMethod();
             if(method.isAnnotationPresent(Auth.class)){//是否使用Auth注解
                 for (Annotation anno : method.getDeclaredAnnotations()){//获得所有的注解
                     if(anno.annotationType().equals(Auth.class)){//找到自己的注解
                    	 methodAuthKindMap.put(method.getName(),new BigDecimal(((Auth)anno).action().getIndex()));
                     }
                 }
             }
        } 
	}
	/**
	 * 缓存action对应的MenuId
	 */
	public static Map<String,BigDecimal> acitonMenuIdMap = new HashMap<String,BigDecimal>();
	private void acitonMenuIdCatche(){
		String sql = "select id,action_class from sys_menu";
		List<SysMenu>  menuList =  jdbcTemplate.queryForListBean(sql, SysMenu.class);
		for (SysMenu s:menuList){
			acitonMenuIdMap.put(s.getActionClass(),s.getId());
		}
	}
}
